/**
 * 
 */
package cn.nawang.ebeim.client.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.nawang.ebeim.client.bean.BackupLog;
import cn.nawang.ebeim.client.bean.ClientConfiguration;
import cn.nawang.ebeim.client.bean.DataSource;
import cn.nawang.ebeim.client.bean.DataSourceVersion;
import cn.nawang.ebeim.client.bean.FileBean;
import cn.nawang.ebeim.client.bean.StorageServer;
import cn.nawang.ebeim.client.bean.TbStorageStrategy;
import cn.nawang.ebeim.client.exception.ApiRequestException;
import cn.nawang.ebeim.client.exception.InitializationException;
import cn.nawang.ebeim.client.version.DirectoryNode;
import cn.nawang.ebeim.client.version.FileNode;
import cn.nawang.ebeim.client.version.Node;

/**
 * @ClassName: CommonMethodsUtils
 * @Description: 公共方法调用
 * @author 张建峰
 * @date 2015年8月28日 上午11:57:33
 * @version v1.0
 */
public class CommonMethodsUtils {

  private static final Logger LOG = LoggerFactory.getLogger(CommonMethodsUtils.class);

  private static int retries;

  /**
   * @author 张建峰
   * @Description: 获取树的本地存储路径
   * @param @param dsId
   * @param @param version
   * @param @return
   * @return String
   * @date 2015年8月28日下午2:10:46
   *
   * @修改人 张建峰
   * @修改日期
   */
  public static String getVersionTreePath(String dsId, DataSourceVersion version) {
    return FileUtil.getZipVersionFilePath(dsId, version.getVersion());
  }

  /**
   * @author 张建峰
   * @Description: 数据库查询，该文件是否已存在
   * @param @param dsId
   * @param @param signature
   * @param @return
   * @return boolean
   * @date 2015年8月28日下午2:12:29
   *
   * @修改人 张建峰
   * @修改日期
   */
  public static boolean exists(String dsId, String signature) {
    boolean isExist = false;
    try {
      isExist = ApiVisitUtil.storageFileIsExist(dsId, signature);
    } catch (ApiRequestException e) {
      // TODO Auto-generated catch block
      LOG.error("fail to exists: {}", e);
      e.printStackTrace();
    }
    return isExist;
  }

  /**
   * @author 张建峰
   * @Description: 文件加密
   * @param @param srcPath
   * @param @param dstPath
   * @param @param fname
   * @return void
   * @date 2015年8月28日下午2:15:30
   *
   * @修改人 张建峰
   * @修改日期
   */
  public static void encrypt(String srcPath, String dstPath, String fname) {
    String password = "";
    try {
      password = ApiUtil.getCriptKey();
    } catch (Exception e) {
      LOG.error("get CriptKey failed...");
      e.printStackTrace();
    }
    long start = System.currentTimeMillis();
    new CipherUtil(CipherUtil.AES, CipherUtil.AES_KEY_SIZE_128)
        .encrypt(srcPath + File.separator + fname, dstPath + File.separator + fname, password);
    long end = System.currentTimeMillis();
    LOG.debug("encrypt file takes {} ms", end - start);
  }

  public static void decrypt(String srcPath, String dstPath) {
    String password = "";
    try {
      password = ApiUtil.getCriptKey();
    } catch (Exception e) {
      LOG.error("get CriptKey failed...");
      e.printStackTrace();
    }
    new CipherUtil(CipherUtil.AES, CipherUtil.AES_KEY_SIZE_128).decrypt(srcPath, dstPath, password);
  }


  /**
   * @author 张建峰
   * @Description: 重新获取存储服务
   * @param @throws InitializationException
   * @return void
   * @date 2015年8月28日下午3:43:04
   *
   * @修改人 张建峰
   * @修改日期
   */
  public static void reGetServer() throws InitializationException {
    List<StorageServer> servers = getServer();
    if (servers == null) {
      throw new InitializationException("get storage server failed");
    }
    ClientConfiguration.setStorageServers(servers);
  }


  /**
   * @author 张建峰
   * @Description: 获取存储服务
   * @param @return
   * @return List<StorageServer>
   * @date 2015年8月28日下午3:41:06
   *
   * @修改人 张建峰
   * @修改日期
   */
  public static List<StorageServer> getServer() {

    List<StorageServer> servers = null;
    StorageServer server = null;

    try {
      servers = new ArrayList<StorageServer>();
      String customerId = PropertiesUtil.read(PropertiesConstants.CUSTOMER_ID);
      LOG.info("getServer--------------------:customerId:" + customerId);
      List<TbStorageStrategy> tss = ApiUtil.findCloudIdByCustomerId(customerId);
      if (tss == null || tss.size() == 0) {
        return null;
      }
      TbStorageStrategy bean = tss.get(0);
      String storageCloudId = bean.getStorageCloudId();
      LOG.info("--------\n------------");
      LOG.info("----------storageCloudId:" + storageCloudId);
      String hosts = getZookeeperHosts(storageCloudId);
      LOG.info("--------\n------------");
      ZookeeperUtil.connect(hosts);
      String name = Constants.ZOOKEEPER_HOST_NAME;
      List<String> list = ZookeeperUtil.getChildNodeList(name);
      for (String li : list) {
        String path = name + "/" + li;
        String serverInfo = ZookeeperUtil.getData(path);
        String[] arrInfo = serverInfo.split(":");
        String ip = arrInfo[0];
        int port = Integer.valueOf(arrInfo[1]);
        server = new StorageServer(ip, port);
        servers.add(server);
      }
      // if(servers == null || servers.size() ==0){
      // ZookeeperUtil.close();
      // }
      return servers;

    } catch (Exception e) {
      e.printStackTrace();
      try {
        ZookeeperUtil.close();
      } catch (InterruptedException e1) {
        e1.printStackTrace();
      }
    }
    return null;
  }


  /**
   * @author zhangjf
   * @Description: TODO
   * @param @param storageCloudId
   * @param @return
   * @return String
   * @date 2015年10月10日上午10:21:23
   *
   * @修改人 zhangjf
   * @修改日期
   */
  public static String getZookeeperHosts(String storageCloudId) {
    String zkHosts = null;
    StringBuffer zkHostsBuffer = new StringBuffer();
    try {
      List<StorageServer> servers = ApiVisitUtil.getStorageCloudServerList(storageCloudId);
      for (int i = 0; i < servers.size(); i++) {
        StorageServer storageServer = servers.get(i);
        if (storageServer.getHost() != null) {
          zkHostsBuffer.append(storageServer.getHost() + ":" + storageServer.getPort() + ",");
        } else {
          zkHostsBuffer.append(
              storageServer.getInternalHost() + ":" + storageServer.getInternalPort() + ",");
        }
      }
      zkHosts = zkHostsBuffer.toString();
      zkHosts = zkHosts.substring(0, zkHosts.lastIndexOf(','));
    } catch (Exception e) {
      e.printStackTrace();
    }
    return zkHosts;
  }

  /**
   * @author 张建峰
   * @Description: 复制文件
   * @param srcPath 源文件
   * @param desPath 目的文件
   * @return void
   * @date 2015年9月17日上午11:55:09
   *
   * @修改人 张建峰
   * @修改日期
   */
  public static void copyFile(String srcPath, String desPath) {

    FileInputStream in = null;
    FileOutputStream out = null;
    try {
      File file = new File(desPath);
      if (!file.getParentFile().exists()) {
        file.getParentFile().mkdirs();
      }
      in = new FileInputStream(srcPath);
      out = new FileOutputStream(file);
      byte[] data = new byte[1024];
      int len = 0;
      while ((len = in.read(data)) != -1) {
        out.write(data, 0, len);
      }
      out.flush();
      out.close();
      in.close();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      closeStream(in, out);
    }

  }

  /**
   * @author zhangjf
   * @Description: 文件重命名的规则
   * @param @param filename
   * @param @param i
   * @param @return
   * @return String
   * @date 2015年11月9日上午8:56:46
   *
   * @修改人 zhangjf
   * @修改日期
   */
  public static String existFileRename(String filename, Integer i) {
    if (i == null) {
      i = 1;
    }
    File file = new File(filename);
    if (file.exists() && file.isFile()) {
      int dotP = filename.lastIndexOf(".");
      String presuffix = filename;
      String suffix = null;
      // 文件名是否有后缀
      if (dotP != -1) {
        // 除去后缀部分
        presuffix = filename.substring(0, dotP);
        // 保存后缀
        suffix = filename.substring(dotP, filename.length());
      }
      // 最后一个字符
      String lastChar = presuffix.substring(presuffix.length() - 1);
      String preChar = "";
      String between = "";
      int preIdx = presuffix.lastIndexOf("(");
      if (preIdx != -1) {
        // 最后一个左括号
        preChar = "(";
        // 最后一个左括号与最后一个字符间的字符
        between = presuffix.substring(preIdx + 1, presuffix.length() - 1);
      }
      String newFilename = null;
      // 判断是否重命名过
      if (preChar.equals("(") && lastChar.equals(")") && isPositiveNum(between)) {
        String forward = presuffix.substring(0, preIdx);
        newFilename = forward + "(" + i + ")";
      } else {
        newFilename = presuffix + "(" + i + ")";
      }
      if (suffix != null) {
        newFilename += suffix;
      }
      File newFile = new File(newFilename);
      // 判断新命名是否存在，若存在，则递归调用自身。
      if (newFile.exists()) {
        filename = existFileRename(newFilename, ++i);
      } else {
        filename = newFilename;
      }
    }

    return filename;
  }

  public static void main(String[] args) throws IOException {
    // for (int i = 0; i < 15; i++) {
    // String rs = existFileRename("F://rename//t(1d)", null);
    // File f = new File(rs);
    // if(!f.exists()){
    // f.createNewFile();
    // }
    // System.out.println(rs);
    // }
    // System.out.println(isPositiveNum("100"));

  }

  /**
   * @author 张建峰
   * @Description: 删除文件夹以及文件夹下的所有文件
   * @param path
   * @return void
   * @date 2015年9月17日下午2:24:39
   *
   * @修改人 张建峰
   * @修改日期
   */
  public static void deleteFolder(String path) {

    File f = new File(path);
    if (f.isDirectory()) {
      File[] files = f.listFiles();
      for (File file : files) {
        deleteFolder(file.getAbsolutePath());
        file.delete();
      }
      f.delete();
    } else {
      f.delete();
    }

  }

  /**
   * @author 张建峰
   * @Description: 流关闭方法
   * @param @param in
   * @param @param out
   * @return void
   * @date 2015年9月30日上午8:56:43
   *
   * @修改人 张建峰
   * @修改日期
   */
  public static void closeStream(InputStream in, OutputStream out) {

    if (in != null) {
      try {
        in.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    if (out != null) {
      try {
        out.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }

  }

  /**
   * @author 张建峰
   * @Description: 判断字符串是否为number
   * @param @param str
   * @param @return
   * @return boolean
   * @date 2015年9月17日下午3:23:42
   *
   * @修改人 张建峰
   * @修改日期
   */
  public static boolean isPositiveNum(String str) {
    Boolean strResult = str.matches("[0-9]+");
    if (strResult == true) {
      return true;
    } else {
      return false;
    }
  }

  public static boolean isNum(String str) {
    Boolean strResult = str.matches("[0-9]+.[0-9]+");
    if (strResult == true) {
      return true;
    } else {
      return false;
    }
  }

  /**
   * @author 张建峰
   * @Description: 排序
   * @param @param list
   * @param @return
   * @return List<Float>
   * @date 2015年9月17日下午3:55:15
   *
   * @修改人 张建峰
   * @修改日期
   */
  public static List<Float> sort(List<Float> list) {
    for (int i = 0; i < list.size(); i++) {
      for (int j = i; j < list.size(); j++) {

        if (list.get(i) > list.get(j)) {
          float tmp = list.get(i);
          list.set(i, list.get(j));
          list.set(j, tmp);
        }
      }
    }
    return list;
  }

  public static void backupLogProcess(String dsId, int majorVersion, int minorVersion, int status,
      Long usedSpace, String description) {
    // 日志处理
    BackupLog newlog = new BackupLog();
    newlog.setDsId(dsId);
    newlog.setVersionMajor(majorVersion);
    newlog.setVersionMinor(minorVersion);
    List<BackupLog> logs = null;
    try {
      logs = ApiUtil.getBackupLogList(newlog);
    } catch (ApiRequestException e) {
      LOG.error("fali to getBackupLogList", e);
      e.printStackTrace();
    }
    if (logs != null && logs.size() > 0) {
      newlog = logs.get(0);
      newlog.setStatus(status);
      newlog.setCaused(description);
      newlog.setUsedSpace(usedSpace);
      newlog.setEndTime(new Date().getTime());
      try {
        ApiUtil.updataBackupLog(newlog);
      } catch (ApiRequestException e) {
        // TODO Auto-generated catch block
        LOG.error("fali to updataBackupLog", e);
        e.printStackTrace();
      }
    }
  }

  public static void addBackupLogProcess(DataSource ds, String remark) {
    BackupLog log = new BackupLog();
    log.setDsId(ds.getId());
    log.setVersionMajor(ds.getNextVersion().getMajorVersion());
    log.setVersionMinor(ds.getNextVersion().getMinorVersion());
    List<BackupLog> logs = null;
    try {
      logs = ApiUtil.getBackupLogList(log);
    } catch (ApiRequestException e) {
      LOG.error("fali to getBackupLogList", e);
      e.printStackTrace();
    }
    if (logs == null || logs.size() == 0) {
      log.setBeginTime(new Date().getTime());
      log.setStatus(Constants.BACKUPLOG_STATUS_UNFINISH);
      log.setCaused("未完成");
      log.setUsedSpace(0l);
      log.setRemark(remark);
      ApiUtil.addBackupLog(log);
    }
  }

  public static FileBean recoveryFilesize(Node node) {
    FileBean bean = new FileBean();
    if (node instanceof DirectoryNode) {

      DirectoryNode dn = (DirectoryNode) node;
      for (String key : dn.getChildren().keySet()) {
        FileBean beanTmp = recoveryFilesize(dn.getChildren().get(key));
        bean.setFileSize(bean.getFileSize() + beanTmp.getFileSize());
        bean.setFileSum(bean.getFileSum() + beanTmp.getFileSum());
      }

    } else {
      FileNode fn = (FileNode) node;
      if (fn.getStatus() != FileNode.STATUS_BEFORE_DELETED
          && fn.getStatus() != FileNode.STATUS_DELETED) {
        bean.setFileSize(bean.getFileSize() + fn.getInfo().getFileSize());
        bean.setFileSum(bean.getFileSum() + 1);
      }
    }
    return bean;
  }

}
